//go:build linux || windows

// Add By : 陈狍子 e4ting@qq.com 2024-05-19 12:31:55

package main

import (
	"fmt"
	"os"

	// "io"
	"bytes"
	"encoding/hex"
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/google/uuid"
)

type DeviceNode struct {
	Name     string `json:"name"`
	Frpc     []byte `json:"-"`
	NodeID   string `json:"nodeid"`
	Hardware INFO   `json:"hardware"`
}

func (self *DeviceNode) Init() {
	self.Name = hex.EncodeToString(uuid.NodeID())
	self.Hardware = INFO{}
	self.Hardware.Init()
	logger.Printf("%+v", self.Hardware)
}

func (self *DeviceNode) ReportHardware() bool {
	url := fmt.Sprintf(`https://api.e4ting.cn/api/v2/bot/info/%s`, self.NodeID)
	data, _ := json.Marshal(self.Hardware)
	resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
	if err != nil {
		logger.Println("网络错误:", err)
		return false
	}
	defer resp.Body.Close()
	return true
}

func Post(url string, postData interface{}, result interface{}) {
	// 将数据编码为JSON
	jsonData, err := json.Marshal(postData)
	if err != nil {
		logger.Println(err)
		return
	}
	logger.Printf("post %v %v", url, string(jsonData))
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		logger.Println(err)
		return
	}
	// 设置Content-Type头，以告诉服务器正文的格式
	req.Header.Set("Content-Type", "application/json")

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logger.Println(err)
		return
	}
	defer resp.Body.Close()
	if err := json.NewDecoder(resp.Body).Decode(result); err != nil {
		logger.Println(err)
		return
	}
	return
}

func (self *DeviceNode) GetUuid() string {

	type Result struct {
		Code   int    `json:"code"`
		NodeID string `json:"data"`
	}
	var result Result
	url := `https://api.e4ting.cn/api/v2/bot/client`
	// self.Name
	Post(url, map[string]interface{}{"uuid": self.Name}, &result)

	// logger.Println(url)
	// resp, err := http.Get(url)
	// if err != nil {
	// 	logger.Println(err)
	// 	return
	// }
	// defer resp.Body.Close()

	// var result Result
	// if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
	// 	logger.Println(err)
	// 	return
	// }
	if result.Code != 200 {
		logger.Println(fmt.Errorf("服务器返回 异常%+v , %+v", result, self))
		return ""
	}
	self.NodeID = result.NodeID
	logger = log.New(os.Stdout, fmt.Sprintf("[%s ]# ", self.NodeID), 0)
	logger.Println(fmt.Sprintf("%+v", result))
	return self.NodeID
}

func (self *DeviceNode) GetFRP() bool {
	url := fmt.Sprintf(`http://consul.e4ting.cn/e4ting/nodes/%s/etc/frpc.yaml?raw`, self.NodeID)
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		logger.Println("网络故障:", err)
		return false
	}

	if resp.StatusCode != http.StatusOK {
		logger.Println("请求失败:", resp.StatusCode)
		return false
	}

	// 读取响应内容
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Println("读取失败:", err)
		return false
	}
	self.Frpc = body
	// file, err := os.Create("./frpc.yaml")
	// defer file.Close()
	// if err != nil {
	// 	logger.Println("创建文件失败:", err)
	// 	return false
	// }

	// _, err = io.Copy(file, resp.Body)
	// if err != nil {
	// 	logger.Println("写入文件失败:", err)
	// 	return false
	// }
	return true
}

func (self *DeviceNode) CreateFRP() bool {

	url := fmt.Sprintf(`https://api.e4ting.cn/api/v2/cluster/frp/%s`, self.NodeID)
	logger.Println(url)
	resp, err := http.Post(url, "", nil)
	if err != nil {
		logger.Println("写入文件失败:", err)
		return false
	}
	defer resp.Body.Close()
	return true
}

func (self *DeviceNode) Cleanup() {
	fuse := Fuse{}
	fuse.Unlink("./frpc.ini")
}
